package com.powernode.proxy.service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/*
 * 专门负责计时的一个调用处理器对象。
 * 这个调用处理器当中编写计算时间相关的增强代码
 * 调用处理器只需要写一个就行了
 */
public class TimerInvocationHandler implements InvocationHandler {

    private Object target;

    public TimerInvocationHandler(Object target) {
        this.target = target;
    }

    /*
            1.为什么强行要求你必须实现接口中的方法。
                  因为一个类实现接口必须实现接口中的方法
                  以下这个方法必须是invoke(),因为JDK在底层调用invoke()方法的程序已经提前写好了
              注意：invoke()方法不是我们程序员负责调用的。而是JDK负责调用的。

            2.invoke方法什么时候被调用呢？
                当代理对象调用代理方法的时候，注册在InvocationHandler调用处理器当中invoke（）方法被JDK调用。

            3.invoke方法的三个参数：
                invoke方法是JDK负责调用的，所以JDK调用这个方法的时候会自动给我们传过来三个参数
                我们可以在invoke方法的大括号中直接使用
                第一个参数：Object proxy 代理对象的引用。这个参数使用的比较少
                第二个参数：Method method 目标对象上的目标方法。（要执行的目标方法就是它）
                第三个参数：Object[] args 目标方法上的实参。
            */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 这个接口的目的就是让你有地方写增强代码。
        // System.out.println("增强1");
        long begin = System.currentTimeMillis();

        // 调用目标对象上的目标方法
        // 方法的四要素：那个对象 哪个方法 传什么参数 返回什么值
        Object retValue = method.invoke(target, args);

        // System.out.println("增强2");
        long end = System.currentTimeMillis();
        System.out.println("耗时" + (end - begin) + "毫秒");

        // 注意这个invoke方法的返回值，如果代理对象调用代理方法之后，需要返回结果的话，invoke方法必须将目标方法执行结果继续返回
        return retValue;
    }
}
